/* Custom CSS for the Rust Specification. */

/* Per-theme variables. */
:root {
    --railroad-background-color: hsl(30, 20%, 95%);
    --railroad-background-image:
        linear-gradient(to right, rgba(30, 30, 30, .05) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(30, 30, 30, .05) 1px, transparent 1px);
    --railroad-path-stroke: black;
    --railroad-rect-stroke: black;
    --railroad-rect-fill: hsl(-290, 70%, 90%);
}
.light {
    --alert-note-color: #0969da;
    --alert-warning-color: #9a6700;
    --alert-edition-color: #1a7f37;
    --alert-example-color: #8250df;
    --grammar-literal-bg: #fafafa;
}
.rust {
    --alert-note-color: #023b95;
    --alert-warning-color: #603700;
    --alert-edition-color: #008200;
    --alert-example-color: #8250df;
    --grammar-literal-bg: #dedede;
}
.light, .rust {
    --grammar-comment-color: lch(from var(--quote-bg) calc(l - 50) 0 0);
    --inline-code-color: var(--grammar-comment-color);
}
.coal, .navy {
    --alert-note-color: #4493f8;
    --alert-warning-color: #d29922;
    --alert-edition-color: #3fb950;
    --alert-example-color: #ab7df8;
    --grammar-literal-bg: #1d1f21;
}
.ayu {
    --alert-note-color: #74b9ff;
    --alert-warning-color: #f0b72f;
    --alert-edition-color: #2bd853;
    --alert-example-color: #d3abff;
    --grammar-literal-bg: #191f26;
}
.coal, .navy, .ayu {
    --grammar-comment-color: lch(from var(--quote-bg) calc(l + 50) 0 0);
    --inline-code-color: var(--grammar-comment-color);
    --railroad-background-color: hsl(230, 10%, 20%);
    --railroad-background-image:
        linear-gradient(to right, rgba(150, 150, 150, .05) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(150, 150, 150, .05) 1px, transparent 1px);
    --railroad-path-stroke: hsl(200, 10%, 60%);
    --railroad-text-fill: hsl(230, 30%, 80%);
    --railroad-rect-stroke: hsl(200, 10%, 50%);
    --railroad-rect-fill: hsl(230, 20%, 20%);
}

/*
.parenthetical class used to keep e.g. "less-than symbol (<)" from wrapping
the end parenthesis onto its own line. Use in a span between the last word and
the parenthetical. So for this example, you'd use
```less-than <span class="parenthetical">symbol (`<`)</span>```
*/
.parenthetical {
    white-space: nowrap;
}

/*
Admonitions are defined with blockquotes:

> [!WARNING]
> This is bad!

See mdbook-spec/src/admonitions.rs.
*/
.alert blockquote {
    /* Add some padding to make the vertical bar a little taller than the text.*/
    padding: 8px 0px 8px 20px;
    /* Add a solid color bar on the left side. */
    border-inline-start-style: solid;
    border-inline-start-width: 4px;
    /* Disable the background color from mdbook for a cleaner look. */
    background-color: inherit;
    /* Disable border blocks from mdbook. */
    border-block-start: none;
    border-block-end: none;
    /* Reduce margin from mdbook, it uses a lot of space. */
    margin: 10px 0;
}

.alert-title {
    /* Slightly increase the weight for more emphasis. */
    font-weight: 600;
    /* Vertically center the icon with the text. */
    display: flex;
    align-items: center;
    /* Remove default large margins for a more compact display.
       Important to override .alert p rule. */
    margin: 0 0 8px 0 !important;
}
.alert blockquote > :nth-child(2) {
    /* Default margins of content just below the label add too much space. */
    margin-top: 0;
}
.alert blockquote > :last-child {
    /* Default margins of content add too much space. */
    margin-bottom: 0;
}

.alert-title svg {
    fill: currentColor;
    /* Add some space between the icon and the text. */
    margin-right: 8px;
}

.alert-note blockquote {
    border-inline-start-color: var(--alert-note-color);
}
.alert-warning blockquote {
    border-inline-start-color: var(--alert-warning-color);
}
.alert-edition blockquote {
    border-inline-start-color: var(--alert-edition-color);
}
.alert-example blockquote {
    border-inline-start-color: var(--alert-example-color);
}
.alert-note .alert-title {
    color: var(--alert-note-color);
}
.alert-warning .alert-title {
    color: var(--alert-warning-color);
}
.alert-edition .alert-title {
    color: var(--alert-edition-color);
}
/* Puts a rounded rectangle around the edition date. */
.alert-title-edition {
    padding: 0px 5px;
    margin-right: 1rem;
    border: 2px solid var(--alert-edition-color);
    border-radius: 15px;
    font-weight: bold;
    color: var(--alert-edition-color);
}
.alert-example .alert-title {
    color: var(--alert-example-color);
}

/* <kbd> tags can be used to highlight specific character elements. */
kbd {
    border: 1px solid #999;
    display: inline-block;
    border-radius: 3px;
    padding: 0 0.6ex;
    background: #eee;
    box-shadow: inset -1px -1px 0 #999;
    vertical-align: baseline;
    color: #000;
    height: 1.55em;
    font-style: normal;
    font-weight: bold;
    font-family: inherit;
    font-size: revert;
    line-height: revert;
}
kbd.optional {
    border-style: dashed;
    background: #fff;
}
var.optional {
    border-style: dashed;
}

/* <var> tags can be used for non-terminals. */
var {
    border: 1px solid #9c9;
    box-shadow: inset -1px -1px 0 #9c9;
    font-style: normal;
    display: inline-block;
    vertical-align: baseline;
    border-radius: 7px;
    padding: 0 4px;
    background: #dfd;
    margin: 2px;
}
var.type {
    box-shadow: inset -1px -1px 0 #c99;
    border-color: #c99;
    background: #fdd;
}

/* <span class="repeat"> can be used for a grammar production that repeats zero or more times. */
span.repeat {
    position: relative;
    border: 1px dashed #393;
    border-radius: 10px;
    display: inline-block;
    padding: 6px;
    margin-left: 0.5ex;
    margin-top: 1em;
    margin-bottom: 0.5ex;
    min-width: 3.8em;
    text-align: center;
}
span.repeat::before {
    content: "zero or more";
    white-space: nowrap;
    display: block;
    text-align: center;
    font-size: 0.75em;
    position: absolute;
    left: 0;
    right: 0;
    top: -1.4em;
    color: #393;
}
var > span {
    display: inline-block;
    border-right: 1px dotted green;
    padding-right: 0.5ex;
    margin-right: 0.5ex;
    font-style: italic;
}

/* <span class="version"> can be used to highlight a specific version of Rust. */
span.version {
    float: right;
    margin-left: 1em;
    margin-bottom: 1em;
    background: #f7c0eb;
    padding: 0.2ex 0.5ex;
    border-radius: 5px;
    display: block;
    box-shadow: inset -1px -1px 0 #a06894;
    font-size: 0.9em;
}

/* <dfn> tags are used to indicate a specific word or phrase is being defined. */
dfn {
    font-style: italic;
    text-decoration: underline;
}

.content main {
    /* Provides space on the left for the rule call-outs. */
    padding-left: 4em;
}

/* Rules are generated via r[foo.bar] syntax, processed by mdbook-spec. */
.rule {
    --font-size-mult: 0.8;
    --font-size: calc(1em * var(--font-size-mult));

    font-size: var(--font-size);
}

/* included in the grid below as 20px */
.page, .content {
    padding-left: 0;
    padding-right: 0;
}
/* required to accommodate above, somehow... */
#mdbook-menu-bar {
    margin-left: 0;
}

main {
    /* To nicely display rules (`[a.b.c]`) on a side of the main text body we
       use grid layout. */
    display: grid;
    grid-template-columns:
        /* Left margin / place for rules */
        [rules] minmax(36px, 1fr)
        /* The main text body */
        [text] auto
        /* Right margin */
        [margin] minmax(36px, 1fr);

    /* We do these by hand via the grid */
    margin: 0;
    padding: 0 !important;
    max-width: none !important;
}

main > * {
    /* By default grid items can't be smaller than their content.
       That is, by default `min-width: auto`.
       We want to be able to force code blocks to be scrollable,
       so we need to overwrite `min-width`. */
    min-width: 0;
    max-width: var(--content-max-width);

    /* All elements should be in the main text body... */
    grid-column: text;
}

main > .rule {
    /* ... except the rules, which must be in the left margin */
    grid-column: rules;
}

hr {
    /* For some reason, grid is shrinking this to a point. */
    width: 100%;
}

/* Too much space with the grid.
*/
.footnote-definition {
    margin-top: 0;
}
.footnote-definition li:first-child > *:first-child {
    margin-top: 0;
}

/* This is quite dumb, ugh.
   CSS doesn't allow margin collapsing between grid items and anything else
   (src: <https://stackoverflow.com/a/37837971>), which means that the margins
   of li's children are not collapsed with ul's margins, adding too much margins.

   Ideally we'd add `<div>`s for each grid cell, so that margin collapsing happens
   as-usual inside of them. But, we don't have that kind of control over mdbook. */
main > ul > li > *:first-child,
main > ul > li > pre:first-child > pre.playground {
    margin-top: 0;
}
main > ul > li > *:last-child,
main > ul > li > pre:last-child > pre.playground {
    margin-bottom: 0;
}

/* Similarly to the above, margin collapse doesn't happen between grid items,
   so we have to replace it with grid gap. (p, pre, and ul had 16px vertical margins) */
main {
    row-gap: 16px;
}
main > p,
main > pre,
main > pre > pre.playground,
main > ul {
    margin-top: 0;
    margin-bottom: 0;
}

/* Values for header margin-top and blockquote margin are taken from mdbook's general.css,
   values for header margin-bottom are taken from <https://www.w3schools.com/cssref/css_default_values.php> */
:root {
    /* 1.6 is body font-size */
    --h2-margin-top: calc(1.5rem * 1.6 * 2.5 - 16px);
    --h3-margin-top: calc(1.17rem * 1.6 * 2.5 - 16px);
    --h4-margin-top: calc(1.00rem * 1.6 * 2 - 16px);
    --h5-margin-top: calc(0.83rem * 1.6 * 2 - 16px);
    --h6-margin-top: calc(0.67rem * 1.6 * 2 - 16px);
}
main > h2 {
    margin-top: var(--h2-margin-top);
    margin-bottom: calc(0.83em - 16px);
}
main > h3 {
    margin-top: var(--h3-margin-top);
    margin-bottom: calc(1em - 16px);
}
main > h4 {
    margin-top: var(--h4-margin-top);
    margin-bottom: calc(1.33em - 16px);
}
main > h5 {
    margin-top: var(--h5-margin-top);
    margin-bottom: calc(1.67em - 16px);
}
main > h6 {
    margin-top: var(--h6-margin-top);
    margin-bottom: calc(2.33em - 16px);
}
main > blockquote {
    margin-top: calc(20px - 16px);
    margin-bottom: calc(20px - 16px);
}

main > .rule {
    max-width: unset;
    justify-self: right;
    width: 100%;
    /* We use a container query to know the size of the "left margin",
       so that we can hide rules is there is not enough space. */
    container-type: inline-size;
    container-name: rule;
}

.rule-link {
    float: right;
    text-align: right;
    padding-right: 10px;
    /* We add `<wbr>` ourselves and only want breaks there */
    word-break: keep-all;
    /* Remove the blue coloring of links on rules that mdbook normally sets. */
    color: #999 !important;
}

/* Test links */
.test-link {
    float: right;
    padding-right: 10px;
}

.rule .popup-container > a {
    float: right;
    text-align: right;
}

/* When clicking a rule, it is added as a URL fragment and the browser will
   navigate to it. This adds an indicator that the linked rule is the one that
   is "current", just like normal headers are in mdbook.
*/
.rule:target .rule-link::before {
    display: inline-block;
    content: "»";
    padding-right: 5px;
}

/* Make it bolder/easier to read when selected. */
.rule:target .rule-link {
    color: var(--fg) !important;
}

/* Dodge » from headings */
/* Note: Some rules have a .tests-popup in the way, so that's why this selects
         either with or without. */
.rule:has(+ h1:target, + .tests-popup + h1:target),
.rule:has(+ h2:target, + .tests-popup + h2:target),
.rule:has(+ h3:target, + .tests-popup + h3:target),
.rule:has(+ h4:target, + .tests-popup + h4:target),
.rule:has(+ h5:target, + .tests-popup + h5:target),
.rule:has(+ h6:target, + .tests-popup + h6:target) {
    padding-right: 24px;
}

/* This positioning is to push the popup down over the header's top margin.
   Ideally I would like the popup to show *below* the header, but I have no idea how to do that.
*/
.tests-popup:has(+ h2) {
    position: relative;
    top: calc(var(--h2-margin-top) + 10px);
}
.tests-popup:has(+ h3) {
    position: relative;
    top: calc(var(--h3-margin-top) + 10px);
}
.tests-popup:has(+ h4) {
    position: relative;
    top: calc(var(--h4-margin-top) + 10px);
}
.tests-popup:has(+ h5) {
    position: relative;
    top: calc(var(--h5-margin-top) + 10px);
}
.tests-popup:has(+ h6) {
    position: relative;
    top: calc(var(--h6-margin-top) + 10px);
}

/* Hide the rules if the width of the container is too small.
   The cutoff point is chosen semi-arbitrary, it felt that
   when `width < 14em`, there are too many breaks. */
@container rule (width < 14em) {
    main > .rule a.rule-link span,
    .test-link > a span {
        display: none;
    }

    main > .rule > a.rule-link::before {
        content: "[*]";
    }

    .test-link > a::before {
        content: "[T]";
    }
}

/* Align rules to various siblings */
.rule:has(+ p, + .tests-popup + p),
.rule:has(+ ul, + .tests-popup + ul) {
    margin-top: calc((1em - var(--font-size)) / var(--font-size-mult) / 2);
}

.rule:has(+ h1, + .tests-popup + h1) {
    align-self: center;
}

.rule:has(+ h2, + .tests-popup + h2) {
    /* multiplying by this turns h2's em into .rule's em*/
    --h2-em-mult: calc(
        (1 / var(--font-size-mult)) /* to main font size */
          * 1.5 /* to h2 font size */
    );

    margin-top: calc(
        /* h2 margin top */
        2.5em * var(--h2-em-mult) - 16px
        /* half of the font size difference */
        + (1em * var(--h2-em-mult) - 1em) / 2
    );
}
.rule:has(+ h3, + .tests-popup + h3) {
    /* multiplying by this turns h3's em into .rule's em*/
    --h3-em-mult: calc(
        (1 / var(--font-size-mult)) /* to main font size */
          * 1.17 /* to h3 font size */
    );

    margin-top: calc(
        /* h3 margin top */
        2.5em * var(--h3-em-mult) - 16px
        /* half of the font size difference */
        + (1em * var(--h3-em-mult) - 1em) / 2
    );
}

.rule:has(+ h4, + .tests-popup + h4) {
    /* multiplying by this turns h4's em into .rule's em*/
    --h4-em-mult: calc(
        (1 / var(--font-size-mult)) /* to main font size */
          * 1 /* to h4 font size */
    );

    margin-top: calc(
        /* h4 margin top */
        2em * var(--h4-em-mult) - 16px
        /* half of the font size difference */
        + (1em * var(--h4-em-mult) - 1em) / 2
    );
}

.rule:has(+ h5, + .tests-popup + h5) {
    /* multiplying by this turns h5's em into .rule's em*/
    --h5-em-mult: calc(
        (1 / var(--font-size-mult)) /* to main font size */
          * 0.83 /* to h5 font size */
    );

    margin-top: calc(
        /* h5 margin top */
        2em * var(--h5-em-mult) - 16px
        /* half of the font size difference */
        + (1em * var(--h5-em-mult) - 1em) / 2
    );
}

.rule:has(+ h6, + .tests-popup + h6) {
    /* multiplying by this turns h6's em into .rule's em*/
    --h6-em-mult: calc(
        (1 / var(--font-size-mult)) /* to main font size */
          * 0.67 /* to h6 font size */
    );

    margin-top: calc(
        /* h6 margin top */
        2em * var(--h6-em-mult) - 16px
        /* half of the font size difference */
        + (1em * var(--h6-em-mult) - 1em) / 2
    );
}

/* Sets the color for [!HISTORY] blockquote admonitions. */
.history > blockquote {
    background: #f7c0eb;
}

/* Provides a anchor container for positioning popups. */
.popup-container {
    position: relative;
}
/* In the test summary page, a convenience class for toggling visibility. */
.popup-hidden {
    display: none;
}
/* In the test summary page, the styling for the uncovered rule popup. */
.uncovered-rules-popup {
    position: absolute;
    left: -250px;
    width: 400px;
    background: var(--bg);
    border-radius: 4px;
    border: 1px solid;
    z-index: 1000;
    padding: 1rem;
}

/* The popup that shows when viewing tests for a specific rule. */
.tests-popup {
    color: var(--fg);
    background: var(--bg);
    border-radius: 4px;
    border: 1px solid;
    z-index: 1000;
    padding: 1rem;
}

/* The box that contains the grammar. */
.grammar-container {
    font-family: var(--mono-font);
    /* Enable absolute positioning for the target chevron. */
    position: relative;
    background-color: var(--quote-bg);
    border-block-start: .1em solid var(--quote-border);
    border-block-end: .1em solid var(--quote-border);
    margin-top: 4px;
    margin-bottom: 4px;
    padding: 0 20px;
}

/* English words inside the grammar. */
.grammar-text {
    font-family: "Open Sans", sans-serif;
}

/* Comments inside the grammar. */
.grammar-comment {
    font-family: "Open Sans", sans-serif;
    color: var(--grammar-comment-color);
}
.grammar-comment code.hljs {
    background: var(--grammar-literal-bg);
}

/* Places a box around literals to differentiate from other grammar punctuation like | and ( . */
.grammar-literal {
    font-family: var(--mono-font);
    border-radius: 4px;
    border: solid 1px var(--theme-popup-border);
    font-weight: bold;
    font-size: var(--code-font-size);
    padding: 1px 4px;
    color: var(--inline-code-color);
}

.grammar-literal {
    background-color: var(--grammar-literal-bg);
}

.grammar-production:target, .railroad-production:target {
    scroll-margin-top: 50vh;
}

.railroad-production {
    /* Enables absolute positioning of the target chevron. */
    position: relative;
}

/* Adds an indicator to the targeted production name. */
.grammar-production:target::before, .railroad-production:target::before {
    content: "»";
    position: absolute;
    left: 3px;
    font-size: 2rem;
    font-weight: bolder;
    /* For some reason, the vertical alignment is slightly off center. This helps
       with that alignment. It was too difficult to try to fix that via
       absolute positioning. */
    line-height: 1;
}

/* Overrides the positioning of the chevron from the rule above. */
.railroad-production:target::before {
    left: -20px;
    top: 8px;
}

/* The toggle button. */
.grammar-toggle-railroad {
    width: 160px;
    padding: 5px 0px;
    border-radius: 5px;
    cursor: pointer;
}

/* This is used to toggle the hidden status of the railroad diagrams. */
.grammar-hidden {
    display: none;
}

svg.railroad {
    background-color: var(--railroad-background-color);
    background-size: 15px 15px;
    background-image: var(--railroad-background-image);
}

svg.railroad rect.railroad_canvas {
    stroke-width: 0px;
    fill: none;
}

svg.railroad path {
    stroke-width: 3px;
    stroke: var(--railroad-path-stroke);
    fill: none;
}

svg.railroad .debug {
    stroke-width: 1px;
    stroke: red;
}

svg.railroad text {
    font: 14px monospace;
    text-anchor: middle;
    fill: var(--railroad-text-fill);
}

svg.railroad .nonterminal text {
    font-weight: bold;
}

svg.railroad text.comment {
    font: italic 12px monospace;
}

svg.railroad rect {
    stroke-width: 3px;
    stroke: var(--railroad-rect-stroke);
    fill: var(--railroad-rect-fill);
}

svg.railroad g.labeledbox>rect {
    stroke-width: 1px;
    stroke: grey;
    stroke-dasharray: 5px;
    fill: rgba(90, 90, 150, .1);
}

svg.railroad g.exceptbox > rect {
    fill:rgba(245, 160, 125, .1);
}
